/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package encryptfile1;

import java.io.*;
import java.security.*;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

/**
 *
 * @author DQ
 */
public class EncryptFile1 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        // TODO code application logic here
        try {
//            byte[] plainData;
//            byte[] encryptedData;
//            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
//            kpg.initialize(2048);
//            KeyPair kp = kpg.genKeyPair();
//            Key publicKey = kp.getPublic();
//            Key privateKey = kp.getPrivate();
//            //KeyFactory fact = KeyFactory.getInstance("AES");
//
//            Cipher enCipher = Cipher.getInstance("RSA");
//            enCipher.init(Cipher.ENCRYPT_MODE, publicKey);
//
//            File f = new File("input.docx");
//            FileInputStream in = new FileInputStream(f);
//            plainData = new byte[(int) f.length()];
//            in.read(plainData);
//            encryptedData = enCipher.doFinal(plainData);
//
//            // Ghi file da ma hoa xong 
//
//            FileOutputStream target = new FileOutputStream(new File("encrypted.docx"));
//            target.write(encryptedData);
//            target.close();
//            
//            Cipher deCipher = Cipher.getInstance("RSA");
//            deCipher.init(Cipher.DECRYPT_MODE, privateKey);
//            
//            File fen = new File("encrypted.docx");
//            FileInputStream fin = new FileInputStream(fen);
//            encryptedData = new byte[(int)fen.length()];
//            fin.read(encryptedData);
//            plainData = deCipher.doFinal(encryptedData);
//            
//            FileOutputStream targetout = new FileOutputStream(new File("decrypted.docx"));
//            targetout.write(plainData);
//            targetout.close();

            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(1024);
            KeyPair kp = kpg.genKeyPair();
            Key publicKey = kp.getPublic();
            Key privateKey = kp.getPrivate();

            String srcFileName = "input.docx";
            String destFileName = "encrypted.docx";
            
            encryptFile(srcFileName, destFileName, publicKey);
            decryptFile(destFileName, "decrypted.docx", privateKey);
        } catch (Exception ex) {
            System.out.println(ex);
        }


    }

    public static void encryptFile(String srcFileName, String destFileName, Key key) throws Exception {
        encryptDecryptFile(srcFileName, destFileName, key, Cipher.ENCRYPT_MODE);
    }

    /**
     * Decrypt file using 1024 RSA encryption
     *     
* @param srcFileName Source file name
     * @param destFileName Destination file name
     * @param key The key. For encryption this is the Private Key and for
     * decryption this is the public key
     * @param cipherMode Cipher Mode
     * @throws Exception
     */
    public static void decryptFile(String srcFileName, String destFileName, Key key) throws Exception {
        encryptDecryptFile(srcFileName, destFileName, key, Cipher.DECRYPT_MODE);
    }

    /**
     * Encrypt and Decrypt files using 1024 RSA encryption
     *     
* @param srcFileName Source file name
     * @param destFileName Destination file name
     * @param key The key. For encryption this is the Private Key and for
     * decryption this is the public key
     * @param cipherMode Cipher Mode
     * @throws Exception
     */
    public static void encryptDecryptFile(String srcFileName, String destFileName, Key key, int cipherMode) throws Exception {
        OutputStream outputWriter = null;
        InputStream inputReader = null;
        System.out.println("srcFileName ----- " + srcFileName);
        System.out.println("destFileName ----- " + destFileName);
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            String textLine = null;
            byte[] buf = cipherMode == Cipher.ENCRYPT_MODE ? new byte[100] : new byte[128];
            int bufl;
// init the Cipher object for Encryption...
            cipher.init(cipherMode, key);
// start FileIO
            outputWriter = new FileOutputStream(destFileName);
            inputReader = new FileInputStream(srcFileName);
            while ((bufl = inputReader.read(buf)) != -1) {
                System.out.println("hi sale");
                byte[] encText = null;
                if (cipherMode == Cipher.ENCRYPT_MODE) {
                    encText = encrypt(copyBytes(buf, bufl), (PublicKey) key);
                } else {
                    encText = decrypt(copyBytes(buf, bufl), (PrivateKey) key);
                }
                System.out.println("encText ----------- " + encText);
                outputWriter.write(encText);
            }
            outputWriter.flush();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (outputWriter != null) {
                    outputWriter.close();
                }
                if (inputReader != null) {
                    inputReader.close();
                }
            } catch (Exception e) {
            }
        }
    }

    public static byte[] copyBytes(byte[] arr, int length) {
        byte[] newArr = null;
        if (arr.length == length) {
            newArr = arr;
        } else {
            newArr = new byte[length];
            for (int i = 0; i < length; i++) {
                newArr[i] = (byte) arr[i];
            }
        }
        System.out.println("newArr -- " + new String(newArr));
        return newArr;
    }

    public static byte[] encrypt(byte[] text, PublicKey key) throws Exception {
        byte[] cipherText = null;
        try {
// get an RSA cipher object and print the provider
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// encrypt the plaintext using the public key
            cipher.init(Cipher.ENCRYPT_MODE, key);
            cipherText = cipher.doFinal(text);
        } catch (Exception e) {
            throw e;
        }
        return cipherText;
    }

    public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception {
        byte[] dectyptedText = null;
        try {
// decrypt the text using the private key
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            try {
                dectyptedText = cipher.doFinal(text);
            } catch (Exception e) {
                System.out.println("Exception ======== " + e);
                e.printStackTrace();
            }
            System.out.println("dectyptedText ----------- " + dectyptedText);
        } catch (Exception e) {
            throw e;
        }
        return dectyptedText;
    }
}
